package winOrDie.Net.P2P;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Vector;

import winOrDie.Net.WoD_Net_Protocol_ASCII;
import winOrDie.Net.Client.WoD_Client_ControlChannel_Event;
import winOrDie.Net.Proxy.Wod_Proxy_Server;
import winOrDie.Net.Server.WoD_Server_Client;
import winOrDie.Net.Server.WoD_Server_ControlChannel_Event;
import winOrDie.Net.Server.WoD_Server_ControlChannel_Listener;

public class WoD_Server_ControlChannel_P2P implements Runnable 
{

	/**
	 * Internal variable to stop this thread.
	 */
	private boolean fIsStopRequested = false;


	private Socket socket = null;
	private InputStream inputStream = null;
	private DataInputStream dataInputStream = null;
	private OutputStream outputStream = null;
	private DataOutputStream dataOutputStream = null;

	private Vector<WoD_Server_ControlChannel_Listener> listeners = null;

	private WoD_Server_Client woDServerClient = null;


	
	
	public WoD_Server_Client getWoDServerClient() {
		return woDServerClient;
	}

	public WoD_Server_ControlChannel_P2P(WoD_Server_Client woDServerClient) throws Exception 
	{
		this.woDServerClient = woDServerClient;

		/*
		 * Initialize socket, inputStream and DataInputStream
		 */
		this.socket = this.woDServerClient.getTcp_Socket();
		try {
			inputStream = this.socket.getInputStream();
			outputStream = this.socket.getOutputStream();
		} catch (Exception e) {
			Exception exception = new Exception("Error on socket inputStream. " + e.getMessage());
			throw exception;
		}
		dataInputStream = new DataInputStream(inputStream);
		dataOutputStream = new DataOutputStream(outputStream);
		
		
		/*
		 * Initialize listeners vector
		 */
		listeners = new Vector<WoD_Server_ControlChannel_Listener>();

	}

	public synchronized void add_WoD_Server_ControlChannel_Listener(WoD_Server_ControlChannel_Listener listener)
	{
		listeners.add(listener);
	}

	public synchronized void remove_WoD_Server_ControlChannel_Listener(WoD_Server_ControlChannel_Listener listener)
	{
		listeners.remove(listener);
	}

	protected void fireEvent(WoD_Server_ControlChannel_Event event)
	{
		for (WoD_Server_ControlChannel_Listener listener : listeners) {
			listener.notify_Event_WoD_Client_ControlChannel(event);
		}
	}

	/** Request that this thread stop running.  */
	public synchronized void requestStop(){
		fIsStopRequested = true;
	}




	@Override
	public void run() {
		String message_UTF = new String();
		while (!fIsStopRequested) {
			try {
				message_UTF = dataInputStream.readUTF();
			} catch (IOException e) {
				/*
				 * Send error to all listeners and stop thread 
				 */
				WoD_Server_ControlChannel_Event event = new WoD_Server_ControlChannel_Event(this);
				event.setEvent_Type(WoD_Server_ControlChannel_Event.CLIENT_ERROR);
				String message = "Error on tcp channel. " + e.getMessage();
				event.setData(message);
				fireEvent(event);
				fIsStopRequested = true;
			}
			parse_TCP_Control_Message(message_UTF);
		}

	}




	private void parse_TCP_Control_Message(String message)
	{
		String header = message.split(" ")[0];

		WoD_Server_ControlChannel_Event event = null;


		event = new WoD_Server_ControlChannel_Event(this);
		event.setWoDServerClient(woDServerClient);
		
		if (header.equals(WoD_Net_Protocol_ASCII.GameMenu.Join_Game))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.JOIN_GAME);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Side))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.SELECT_SIDE);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Select_Rol))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.SELECT_ROL);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Chat))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.CHAT);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Leave_Game))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.LEAVE_GAME);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Ready_to_Go))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.READY_TO_GO);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Force_Start))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.FORCE_START);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Change_Map))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.CHANGE_MAP);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.GameRoom.Change_Time))
		{
			event.setEvent_Type(WoD_Server_ControlChannel_Event.CHANGE_TIME);
			event.setData(message);
			fireEvent(event);
		}
		else if (header.equals(WoD_Net_Protocol_ASCII.Proxy.Proxy))
		{
			Wod_Proxy_Server.proxy_Message_to_Send(woDServerClient, message);
		}
	}


	public synchronized void sendData(String message) throws Exception
	{
		try {
			dataOutputStream.writeUTF(message);
		} catch (IOException e) {
			Exception exception = new Exception("Error sending data. " + e.getMessage());
			throw exception;
		}
	}

	


	
}
